<template>
  <div class="chat-window">
    <div class="chat-header">
      <ModelSelector
        v-model="selectedModel"
        v-model:deepThinking="deepThinking"
        :models="models"
        @change="handleModelChange"
        @deep-thinking-change="handleDeepThinkingChange"
      />
    </div>
    <div class="chat-messages" ref="msgBox">
      <MessageBubble
        v-for="(msg, i) in session?.messages ?? []"
        :key="i"
        :message="msg"
      />
    </div>
    <div class="chat-footer">
      <div class="input-container">
        <!-- 图片预览区域 -->
        <div v-if="uploadedImages.length > 0" class="image-preview-container">
          <div 
            v-for="(image, index) in uploadedImages" 
            :key="index"
            class="image-preview-item"
            :class="{ uploading: image.uploading }"
          >
            <div class="image-wrapper">
              <img :src="image.url" :alt="image.name" />
              <!-- 上传中的遮罩 -->
              <div v-if="image.uploading" class="upload-overlay">
                <el-icon class="upload-loading"><Loading /></el-icon>
              </div>
            </div>
            <el-button 
              type="danger" 
              size="small" 
              circle 
              @click="removeImage(index)"
              class="remove-image-btn"
              :disabled="image.uploading"
            >
              <el-icon><Close /></el-icon>
            </el-button>
            <div class="image-name">{{ image.name }}</div>
          </div>
        </div>
        
        <!-- 自定义输入框容器 -->
        <div class="custom-input-wrapper">
          <!-- 图片选择按钮 -->
          <div class="input-actions-left">
            <input
              ref="fileInput"
              type="file"
              accept="image/*"
              multiple
              style="display: none"
              @change="onFileSelect"
            />
            <el-button 
              type="text" 
              size="large"
              :disabled="sending || uploadedImages.length >= 5"
              class="upload-btn"
              :title="getUploadButtonTitle()"
              @click="triggerFileSelect"
            >
              <el-icon v-if="!hasUploadingImages"><Picture /></el-icon>
              <el-icon v-else class="is-loading"><Loading /></el-icon>
            </el-button>
          </div>
          
          <!-- 输入框主体 -->
          <div class="input-main">
            <el-input
              v-model="input"
              placeholder="请输入你的问题… (按 Enter 发送)"
              @keydown.enter.native="send"
              clearable
              size="large"
              :disabled="sending"
              class="chat-input"
              type="textarea"
              :autosize="{ minRows: 1, maxRows: 4 }"
              resize="none"
            />
          </div>
          
          <!-- 发送按钮 -->
          <div class="input-actions-right">
            <el-button
              type="primary"
              size="large"
              :loading="sending"
              @click="send"
              :disabled="sending || (!input.trim() && uploadedImages.length === 0) || hasUploadingImages"
              class="send-button"
            >
              <el-icon v-if="!sending"><Promotion /></el-icon>
              <el-icon v-else><Loading /></el-icon>
            </el-button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, watch, nextTick, reactive, onMounted, computed } from 'vue'
import MessageBubble from './MessageBubble.vue'
import { defineExpose } from 'vue'
import axios from '@/utils/axios'
import ModelSelector from '@/components/ModelSelector.vue'
import { ElMessage } from 'element-plus'
import { Picture, Close, Promotion, Loading } from '@element-plus/icons-vue'

const props = defineProps({ session: Object })
const input = ref('')
const msgBox = ref(null)
const sending = ref(false)
// 🔥 新增 'update-session' 事件，用于通知父组件保存会话
const emit = defineEmits(['refresh-sessions', 'select-session', 'update-session']) 
const models = ref([]) 

// 图片相关状态
const uploadedImages = ref([])
const fileInput = ref(null)

// 计算属性
const hasUploadingImages = computed(() => 
  uploadedImages.value.some(img => img.uploading)
)

// 从 localStorage 恢复设置
const selectedModel = ref(localStorage.getItem('ai-selected-model') || '')
const deepThinking = ref(JSON.parse(localStorage.getItem('ai-deep-thinking') || 'false'))

// `pendingFirstMsg` 和 `pendingAssistantMsg` 逻辑在大部分场景下是不必要的，
// 因为 `props.session.messages.push` 已经具有响应式。
// 如果你确认没有特殊场景需要先暂存消息再添加，可以移除这部分。
// 为了简化和聚焦当前 bug，暂时移除此逻辑。
/*
const pendingFirstMsg = ref(null)
const pendingAssistantMsg = ref(null)

watch(
  () => props.session?.sessionId,
  (val, oldVal) => {
    if (
      val && 
      pendingFirstMsg.value && 
      pendingAssistantMsg.value && 
      (Array.isArray(props.session.messages))
    ) {
      props.session.messages.push(pendingFirstMsg.value)
      props.session.messages.push(pendingAssistantMsg.value)
      pendingFirstMsg.value = null
      pendingAssistantMsg.value = null
    }
  }
)
*/

// 监听并持久化设置
watch(selectedModel, (newVal) => {
  if (newVal) {
    localStorage.setItem('ai-selected-model', newVal)
  }
})

watch(deepThinking, (newVal) => {
  localStorage.setItem('ai-deep-thinking', JSON.stringify(newVal))
})

async function fetchModels() {
  try {
    const arr = await axios.get('/ai/modelList')
    console.log(arr)
    models.value = arr.data.map(item => ({
      label: item.modelName,
      value: item.modelName
    }))
    
    // 恢复保存的模型选择，优先级：localStorage > session.model > 第一个模型
    const savedModel = localStorage.getItem('ai-selected-model')
    if (savedModel && models.value.some(m => m.value === savedModel)) {
      selectedModel.value = savedModel
    } else if (props.session?.model && models.value.some(m => m.value === props.session.model)) {
      selectedModel.value = props.session.model
    } else if (models.value[0]?.value) {
      selectedModel.value = models.value[0].value
    }
    
  } catch (e) {
    console.error('获取模型列表失败:', e)
    models.value = [
      { label: 'Qwen-Plus', value: 'qwen-plus' }
    ]
    // 如果没有保存的模型，使用默认模型
    if (!selectedModel.value) {
      selectedModel.value = 'qwen-plus'
    }
  }
}

// 组件加载时拉取模型
onMounted(() => {
  fetchModels()
  
  // 恢复深度思考设置
  const savedDeepThinking = localStorage.getItem('ai-deep-thinking')
  if (savedDeepThinking !== null) {
    deepThinking.value = JSON.parse(savedDeepThinking)
  }
})

// 会话变化时同步当前模型（但不覆盖用户的持久化选择）
watch(
  () => props.session?.model,
  (val) => {
    // 只有在没有保存的模型选择时，才使用会话中的模型
    const savedModel = localStorage.getItem('ai-selected-model')
    if (!savedModel && val && models.value.some(m => m.value === val)) {
      selectedModel.value = val
    }
  },
  { immediate: true }
)


function handleModelChange(val) {
  selectedModel.value = val
  // 同时更新当前会话的模型（如果存在），并通知父组件保存
  if (props.session) {
    props.session.model = val;
    // 🔥 模型切换后通知父组件更新会话（因为会话对象本身的模型属性变了）
    emit('update-session', props.session);
  }
}

function handleDeepThinkingChange(val) {
  deepThinking.value = val
}

// 🔥 触发文件选择
function triggerFileSelect() {
  if (uploadedImages.value.length >= 5) {
    ElMessage.warning('最多只能上传5张图片!')
    return
  }
  fileInput.value?.click()
}

// 🔥 文件选择处理
async function onFileSelect(event) {
  const files = Array.from(event.target.files)
  
  if (files.length === 0) return
  
  // 检查文件数量限制
  if (uploadedImages.value.length + files.length > 5) {
    ElMessage.warning('最多只能上传5张图片!')
    return
  }
  
  // 逐个处理文件
  for (const file of files) {
    if (await validateAndUploadFile(file)) {
      // 文件验证通过，开始上传
    }
  }
  
  // 清空文件选择
  event.target.value = ''
}

// 🔥 验证并上传文件
async function validateAndUploadFile(file) {
  // 文件类型验证
  if (!file.type.startsWith('image/')) {
    ElMessage.error(`${file.name} 不是图片文件!`)
    return false
  }
  
  // 文件大小验证
  if (file.size > 10 * 1024 * 1024) {
    ElMessage.error(`${file.name} 文件大小超过10MB!`)
    return false
  }
  
  // 创建预览URL
  const previewUrl = URL.createObjectURL(file)
  
  // 添加到列表（显示上传中状态）
  const imageItem = {
    name: file.name,
    url: previewUrl,  // 临时预览URL
    uploading: true,
    size: file.size,
    type: file.type,
    file: file // 保留原始文件引用，方便后续识别
  }
  
  uploadedImages.value.push(imageItem)
  
  try {
    // 🔥 调用上传方法
    const result = await uploadFileToServer(file)
    
    // 上传成功，更新数据
    const index = uploadedImages.value.findIndex(img => img.file === file)
    if (index !== -1) {
      // 释放临时URL
      URL.revokeObjectURL(previewUrl)
      
      // 更新为服务器返回的数据
      uploadedImages.value[index] = {
        name: file.name,
        url: result.url,           // 服务器返回的访问URL
        minioPath: result.path,    // MinIO路径
        uploading: false,
        size: file.size,
        type: file.type
      }
      
      ElMessage.success(`${file.name} 上传成功!`)
    }
    
    return true
  } catch (error) {
    console.error('文件上传失败:', error)
    
    // 上传失败，从列表中移除
    const index = uploadedImages.value.findIndex(img => img.file === file)
    if (index !== -1) {
      URL.revokeObjectURL(previewUrl)
      uploadedImages.value.splice(index, 1)
    }
    
    // 根据错误类型显示不同消息
    if (error.response?.status === 413) {
      ElMessage.error(`${file.name} 文件过大!`)
    } else if (error.response?.status === 401) {
      ElMessage.error('登录已过期，请重新登录!')
    } else if (error.response?.status === 500) {
      ElMessage.error(`${file.name} 服务器错误!`)
    } else {
      ElMessage.error(`${file.name} 上传失败: ${error.message || '未知错误'}`)
    }
    
    return false
  }
}

// 🔥 上传文件到服务器的核心方法
async function uploadFileToServer(file) {
  const formData = new FormData()
  formData.append('file', file)
  
  const token = localStorage.getItem('token')
  
  try {
    const response = await axios.post('/file', formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
        'Authorization': `Bearer ${token}`
      },
      timeout: 30000
    })
    
    console.log('完整上传响应:', response)
    
    if (response.code === 200 && response.data) {
      const url = response.data
      
      // 验证URL格式是否正确
      if (!url.startsWith('http')) {
        throw new Error('返回的URL格式不正确')
      }
      
      // 从完整URL中提取路径部分（可选）
      let path
      try {
        const urlObj = new URL(url)
        path = urlObj.pathname
      } catch (e) {
        path = url // 如果解析失败，直接使用完整URL
      }
      
      console.log('处理后的结果:', { url, path })
      
      return {
        url: url,
        path: path
      }
    } else {
      throw new Error(response.message || '上传失败')
    }
  } catch (error) {
    console.error('上传请求失败:', error)
    throw error
  }
}

// 获取上传按钮提示文字
function getUploadButtonTitle() {
  if (hasUploadingImages.value) {
    return '正在上传中...'
  } else if (uploadedImages.value.length >= 5) {
    return '最多上传5张图片'
  } else {
    return '上传图片'
  }
}

// 移除图片
function removeImage(index) {
  const image = uploadedImages.value[index]
  
  // 如果是本地预览URL，需要释放
  if (image.url && image.url.startsWith('blob:')) {
    URL.revokeObjectURL(image.url)
  }
  
  uploadedImages.value.splice(index, 1)
}

// 父组件用来获取/设置滚动条位置的方法
function getScrollTop() {
  return msgBox.value ? msgBox.value.scrollTop : 0
}

function setScrollTop(value) {
  if (msgBox.value) msgBox.value.scrollTop = value
}

defineExpose({ getScrollTop, setScrollTop })

// 🔥 构建后端需要的内容格式
function buildContentForBackend() {
  const content = []
  
  // 添加所有图片，每张图片一个对象
  // 确保这里使用 minioPath，因为后端需要的是存储路径而非临时预览 URL
  uploadedImages.value.forEach(img => {
    content.push({ "image": img.minioPath || img.url }) 
  })
  
  // 添加文本（如果有）
  const text = input.value.trim()
  if (text) {
    content.push({ "text": text })
  }
  
  return content
}

async function send() {
  const text = input.value.trim()
  const hasImages = uploadedImages.value.length > 0
  
  if ((!text && !hasImages) || sending.value) return
  
  // 检查是否还有图片在上传中
  if (hasUploadingImages.value) {
    ElMessage.warning('请等待图片上传完成后再发送!')
    return
  }
  
  sending.value = true

  // 🔥 构建发送给后端的内容格式
  const contentForBackend = buildContentForBackend()

  // 构建前端显示用的消息内容
  let messageContent
  if (hasImages) {
    // 多媒体消息格式 - 用于前端显示
    messageContent = {
      text: text || '',
      images: uploadedImages.value.map(img => ({
        url: img.url,
        name: img.name,
        path: img.minioPath, // 使用 minioPath 以便与后端保持一致
        size: img.size,
        type: img.type
      }))
    }
  } else {
    // 纯文本消息格式（保持向后兼容）
    messageContent = text
  }

  // 创建用户消息，并添加到当前会话中
  const userMsg = { 
    role: 'user', 
    content: messageContent, 
    deepThinking: deepThinking.value,
    timestamp: new Date().toISOString() // 添加时间戳
  }
  props.session.messages.push(userMsg)
  
  // 创建助手消息的占位符，用于流式更新
  const assistantMsg = reactive({ 
    role: 'assistant', 
    content: '', 
    deepThinking: deepThinking.value, 
    reasonContent: '',
    timestamp: new Date().toISOString() // 添加时间戳
  })
  props.session.messages.push(assistantMsg)

  scrollToBottom()

  const token = localStorage.getItem('token')
  
  // 🔥 构建发送给后端的载荷
  const payload = {
    model: selectedModel.value,
    deepThinking: deepThinking.value,
    content: contentForBackend  // 使用格式化后的内容数组
  }
  
  // 如果是现有会话，带上会话 ID
  if (props.session.sessionId) payload.id = props.session.sessionId

  console.log('发送给后端的数据格式:', JSON.stringify(payload, null, 2))

  try {
    const response = await fetch('/api/ai/sse', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${token}`
      },
      body: JSON.stringify(payload)
    })

    if (!response.body) throw new Error('没有SSE流')

    let isFirstChunk = true
    const reader = response.body.getReader()
    const decoder = new TextDecoder('utf-8')
    let partial = ''

    function read() {
      reader.read().then(async ({ done, value }) => {
        if (done) {
          sending.value = false
          scrollToBottom()
          // 🔥 **最关键的改变：** SSE 流结束后，通知父组件保存会话。
          // 此时 `props.session` 已经包含了所有用户和助手的消息。
          emit('update-session', props.session); 
          return;
        }
        partial += decoder.decode(value, { stream: true })
        let lines = partial.split('\n')
        partial = lines.pop()

        for (let line of lines) {
          if (!line.trim()) continue
          if (line.startsWith('data:')) {
            const json = line.replace(/^data:\s*/, '')
            if (!json || json === '[DONE]') continue
            try {
              const obj = JSON.parse(json)
              // 更新助手消息内容
              if ('content' in obj) assistantMsg.content += obj.content || ''
              // 更新深度思考内容
              if ('reasonContent' in obj) assistantMsg.reasonContent += obj.reasonContent || ''

              // 🔥 **新会话 ID 处理：** 如果是新会话（当前 `sessionId` 为空）并且后端返回了 `sessionId`
              if (isFirstChunk && !props.session.sessionId && obj.sessionId) {
                isFirstChunk = false;
                props.session.sessionId = obj.sessionId; // 将后端返回的真实 ID 赋值给会话对象
                props.session.model = selectedModel.value; // 将当前选中的模型保存到会话
                // 为新会话设置一个初始标题 (可以根据用户消息内容生成)
                props.session.title = userMsg.content.text || '新对话'; 
                // 根据是否有图片设置会话类型
                props.session.type = hasImages ? 'multimodal' : 'text'; 

                // 🔥 **新会话 ID 获得后，立即通知父组件更新并保存这个会话**
                // 此时 `props.session` 已经是带有真实 `sessionId` 和初始化信息的对象。
                emit('update-session', props.session); 
                // 通知侧边栏刷新列表，以便显示这个新的会话
                emit('refresh-sessions'); 
              }
              scrollToBottom()
            } catch (e) {
              console.error('JSON 解析失败:', e)
            }
          }
        }
        read()
      }).catch(error => {
        console.error('读取流失败:', error)
        // 🔥 流读取失败时，也通知父组件保存会话，以防部分消息丢失
        emit('update-session', props.session);
        sending.value = false
        scrollToBottom()
      })
    }
    read()
  } catch (e) {
    console.error('发送消息失败:', e)
    assistantMsg.content += '\n[助手消息流式失败]'
    // 🔥 发送请求整体失败时，也通知父组件保存会话（至少用户消息已添加）
    emit('update-session', props.session);
    sending.value = false
    scrollToBottom()
  }
  
  // 清空输入和图片
  input.value = ''
  uploadedImages.value = []
}

function scrollToBottom() {
  nextTick(() => {
    if (msgBox.value) {
      msgBox.value.scrollTop = msgBox.value.scrollHeight
    }
  })
}

watch(
  () => props.session?.messages?.length ?? 0,
  scrollToBottom
)
</script>

<style scoped>
/* 样式部分保持不变 */
.chat-window {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: linear-gradient(135deg, #f6f8fc 0%, #f0f4f7 100%);
  position: relative;
}

.chat-header {
  padding: 16px 24px 12px 24px;
  display: flex;
  align-items: center;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(235, 238, 245, 0.6);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  position: sticky;
  top: 0;
  z-index: 10;
  transition: all 0.3s ease;
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 24px 24px 16px 24px;
  box-sizing: border-box;
  position: relative;
  /* 美化滚动条 */
  scrollbar-width: thin;
  scrollbar-color: rgba(144, 147, 153, 0.3) transparent;
}

.chat-messages::-webkit-scrollbar {
  width: 6px;
}

.chat-messages::-webkit-scrollbar-track {
  background: transparent;
}

.chat-messages::-webkit-scrollbar-thumb {
  background: rgba(144, 147, 153, 0.3);
  border-radius: 3px;
  transition: background 0.3s ease;
}

.chat-messages::-webkit-scrollbar-thumb:hover {
  background: rgba(144, 147, 153, 0.5);
}

.chat-footer {
  padding: 20px 24px 24px 24px;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
  border-top: 1px solid rgba(235, 238, 245, 0.6);
  box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.05);
  position: sticky;
  bottom: 0;
  z-index: 10;
}

.input-container {
  position: relative;
  max-width: 800px;
  margin: 0 auto;
}

/* 图片预览容器 */
.image-preview-container {
  display: flex;
  gap: 12px;
  padding: 16px;
  background: rgba(255, 255, 255, 0.95);
  border-radius: 16px 16px 4px 4px;
  margin-bottom: 2px;
  flex-wrap: wrap;
  border: 2px solid #e4e7ed;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  animation: slideDown 0.3s ease-out;
}

@keyframes slideDown {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.image-preview-item {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  transition: transform 0.2s ease;
}

.image-preview-item:hover:not(.uploading) {
  transform: scale(1.02);
}

.image-preview-item.uploading {
  opacity: 0.8;
}

.image-wrapper {
  position: relative;
  display: inline-block;
}

.image-preview-item img {
  width: 80px;
  height: 80px;
  object-fit: cover;
  border-radius: 8px;
  border: 2px solid #e4e7ed;
  transition: border-color 0.2s ease;
}

.image-preview-item:hover:not(.uploading) img {
  border-color: #409eff;
}

/* 上传中的遮罩 */
.upload-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.upload-loading {
  color: white;
  font-size: 20px;
  animation: rotate 1s linear infinite;
}

@keyframes rotate {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.remove-image-btn {
  position: absolute;
  top: -8px;
  right: -8px;
  width: 22px !important;
  height: 22px !important;
  min-height: 22px !important;
  padding: 0 !important;
  background: #f56c6c !important;
  border: 2px solid white !important;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  transition: all 0.2s ease;
}

.remove-image-btn:hover:not(:disabled) {
  background: #f78989 !important;
  transform: scale(1.1);
}

.remove-image-btn:disabled {
  opacity: 0.5 !important;
  cursor: not-allowed !important;
}

.image-name {
  margin-top: 8px;
  font-size: 12px;
  color: #606266;
  text-align: center;
  word-break: break-all;
  max-width: 80px;
  line-height: 1.2;
}

/* 自定义输入框包装器 */
.custom-input-wrapper {
  display: flex;
  align-items: flex-end;
  background: white;
  border-radius: 16px;
  border: 2px solid #e4e7ed;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
  transition: all 0.3s ease;
  overflow: hidden;
}

.custom-input-wrapper:hover {
  border-color: #c0c4cc;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.12);
}

.custom-input-wrapper:focus-within {
  border-color: #409eff;
  box-shadow: 0 6px 28px rgba(64, 158, 255, 0.25);
  transform: translateY(-1px);
}

/* 左侧操作区 */
.input-actions-left {
  display: flex;
  align-items: center;
  padding: 8px 4px 8px 12px;
  border-right: 1px solid #f0f0f0;
}

/* 输入框主体区域 */
.input-main {
  flex: 1;
  padding: 4px;
}

.chat-input {
  border: none !important;
  box-shadow: none !important;
}

.chat-input :deep(.el-textarea__inner) {
  border: none !important;
  box-shadow: none !important;
  background: transparent !important;
  resize: none !important;
  padding: 12px 16px !important;
  font-size: 15px !important;
  line-height: 1.5 !important;
  color: #303133 !important;
  min-height: 44px !important;
}

.chat-input :deep(.el-textarea__inner)::placeholder {
  color: #a8abb2;
  font-weight: 400;
}

/* 右侧操作区 */
.input-actions-right {
  display: flex;
  align-items: center;
  padding: 8px 12px 8px 4px;
  border-left: 1px solid #f0f0f0;
}

/* 上传按钮样式 */
.upload-btn {
  padding: 8px !important;
  color: #606266 !important;
  transition: all 0.3s ease !important;
  border-radius: 8px !important;
  width: 40px !important;
  height: 40px !important;
}

.upload-btn:hover:not(:disabled) {
  color: #409eff !important;
  background: rgba(64, 158, 255, 0.1) !important;
}

.upload-btn:disabled {
  color: #c0c4cc !important;
  cursor: not-allowed !important;
}

.upload-btn .is-loading {
  animation: rotate 1s linear infinite;
}

/* 发送按钮样式 */
.send-button {
  width: 44px !important;
  height: 44px !important;
  border-radius: 12px !important;
  padding: 0 !important;
  background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%) !important;
  border: none !important;
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3) !important;
  transition: all 0.3s ease !important;
}

.send-button:hover:not(:disabled) {
  transform: translateY(-2px) !important;
  box-shadow: 0 6px 16px rgba(64, 158, 255, 0.4) !important;
}

.send-button:active {
  transform: translateY(0) !important;
}

.send-button:disabled {
  background: #c0c4cc !important;
  box-shadow: none !important;
  transform: none !important;
  cursor: not-allowed !important;
}

.send-button .el-icon {
  font-size: 18px !important;
  color: white !important;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .chat-header {
    padding: 12px 16px 8px 16px;
  }
  
  .chat-messages {
    padding: 16px 16px 12px 16px;
  }
  
  .chat-footer {
    padding: 16px 16px 20px 16px;
  }
  
  .input-container {
    max-width: 100%;
  }
  
  .image-preview-container {
    padding: 12px;
    margin-bottom: 2px;
    gap: 8px;
  }
  
  .image-preview-item img {
    width: 60px;
    height: 60px;
  }
  
  .image-name {
    max-width: 60px;
  }
  
  .custom-input-wrapper {
    border-radius: 12px;
  }
  
  .input-actions-left,
  .input-actions-right {
    padding: 6px 8px;
  }
  
  .upload-btn {
    width: 36px !important;
    height: 36px !important;
  }
  
  .send-button {
    width: 40px !important;
    height: 40px !important;
    border-radius: 10px !important;
  }
  
  .send-button .el-icon {
    font-size: 16px !important;
  }
  
  .chat-input :deep(.el-textarea__inner) {
    font-size: 16px !important; /* 防止移动端缩放 */
    padding: 10px 12px !important;
    min-height: 40px !important;
  }
}

/* 输入框聚焦时的动画 */
.custom-input-wrapper:focus-within .input-actions-left,
.custom-input-wrapper:focus-within .input-actions-right {
  background: rgba(64, 158, 255, 0.02);
}

/* 加载状态动画 */
@keyframes pulse {
  0% { opacity: 1; }
  50% { opacity: 0.7; }
  100% { opacity: 1; }
}

.send-button.is-loading {
  animation: pulse 1.5s ease-in-out infinite;
}

/* 图片预览与输入框连接效果 */
.image-preview-container + .custom-input-wrapper {
  border-radius: 4px 4px 16px 16px;
  border-top: none;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
}

.image-preview-container + .custom-input-wrapper:hover {
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.12);
}

.image-preview-container + .custom-input-wrapper:focus-within {
  box-shadow: 0 6px 28px rgba(64, 158, 255, 0.25);
}
</style>
